/******************************************************************************
 * Copyright (C) 2017 ShenZhen Powerdata Information Technology Co.,Ltd All Rights Reserved.
 * 本软件为深圳博安达开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、 复制、修改或发布本软件.
 *****************************************************************************/

package com.szboanda.platform.common.utils;

import com.szboanda.platform.common.base.BaseException;
import com.szboanda.platform.system.filenumber.service.IFileNumberService;
import org.apache.log4j.Logger;

import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.*;

/**
 * 系统序列号生成器。此类为单例模式，使用时需要先得到实例对象IDGenerator.getInstance()再使用。<br/>
 * 下面给出了一些如何使用IDGenerator的示例： <blockquote>
 *
 * <pre>
 * 生成唯一的序列号
 * IDGenerator.getInstance().generate()
 * </pre>
 *
 * </blockquote>
 *
 * @author 李东喜
 * @version 2016-9-14
 * @Company 深圳市博安达软件开发有限公司
 * @since V0.1.0
 */
public final class IDGenerator {

    /**
     * 日志记录对象
     */
    private static final Logger LOG = Logger.getLogger(IDGenerator.class);

    /*    *//** JdbcDAO 数据库操作对象 *//*
     * private JdbcDAO dao = new JdbcDAO();
     */

    /**
     * 当前类的实例
     */
    private static final IDGenerator INSTANCE = new IDGenerator();

    /**
     * 系统序列号格式
     */
    public static final String FORMAT_TAB;

    /**
     * 当前系统序列号
     */
    public static final String CURRENT_TAB;

    /**
     * 文件数字服务
     */
    private IFileNumberService fileNumberService;

    static {
        FORMAT_TAB = "T_ADMIN_XTGL_SXHDY";
        CURRENT_TAB = "T_ADMIN_XTGL_XTXH";
    }

    /**
     * 私有无参构造方法， 将帮助类修改为单例模式
     *
     * @author 康庆
     * @version 2009-04-02
     * @since V0.1.0
     */
    private IDGenerator() {
    }

    /**
     * 构造当前对象的为单例
     *
     * @since V0.1.0
     */
    public static IDGenerator getInstance() {
        return INSTANCE;
    }

    /**
     * 生成唯一主键 使用当前时间 + UUID ，UUID前增加时间主要是提高索引效率
     *
     * @return 唯一序列号
     *
     * @author 康庆
     * @version 2009-4-2
     * @since V0.1.0
     */
    /*
     * public String generate(){ return DateUtils.stringFormat(new Date(),DateUtils.YYYYMMDDHHMMSS) +
     * UUID.randomUUID().toString().replace("-","") ; }
     */

    /**
     * 获得系统序列号,不需要传链接过来，从本地线程中取链接。
     *
     * @param orgid 组织代码
     * @param bhmc  编号名称
     * @param sfgx  是否更新
     * @return 唯一序列号
     * @author 康庆
     * @version 2009-4-2
     * @since V0.1.0
     */
    public String generate(String orgid, String bhmc, boolean sfgx) {
        try {
            if (null == fileNumberService) {
                fileNumberService = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return this.generate(fileNumberService, orgid, bhmc, sfgx);
    }

    /**
     * 根据用户填写的文号更新系统中当前文号
     *
     * @param orgid
     * @param bhmc
     * @param currentValue
     * @return java.lang.String
     * @throws
     * @author 梁磊
     * @date 2020-01-08 15:21
     */
    public String updateSequenceCurrentValue(
            String orgid, String bhmc, String currentValue
    ) {
        try {
            if (null == fileNumberService) {
                fileNumberService = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                updateSequenceCurrentValue(orgid, bhmc, currentValue);
            } else {
                // 取出格式定义
                List<Map<String, Object>> seq = getXtcsgs(fileNumberService, bhmc, orgid);
                if (null == seq || 0 == seq.size()) {
                    throw new BaseException("不能获得名称是【" + bhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                }
                String qz = (String) seq.get(0).get("QZGS"); // 前缀
                if (StringUtils.hasText(qz)) {
                    qz = qz.toUpperCase();
                } else {
                    qz = "";
                }
                String hz = (String) seq.get(0).get("HZGS");// 后缀
                if (StringUtils.hasText(hz)) {
                    hz = hz.toUpperCase();
                } else {
                    hz = "";
                }
                // 流水号格式
                String no = (String) seq.get(0).get("LSHGS");// 后缀
                if (StringUtils.hasText(no)) {
                    no = no.toUpperCase();
                } else {
                    no = "";
                }
                qz = formatPrefix(qz, orgid);
                hz = formatPrefix(hz, orgid);
                DecimalFormat format = new DecimalFormat(no);
                seq.get(0).put("QZ", qz);
                seq.get(0).put("HZ", hz);
                int i = currentValue.lastIndexOf(hz);
                int last;
                if (i > -1) {
                    last = i;
                } else {
                    last = currentValue.length();
                }
                currentValue = currentValue.substring(qz.length(), last);
                Number dqz = format.parse(currentValue);
                LOG.info("【" + bhmc + "】当前编号为【" + dqz + "】");
                this.updateCurrValue(seq, fileNumberService, true, dqz.intValue());
            }
        }catch (RuntimeException e) {
            throw e;
        }  catch (Exception e) {
            e.printStackTrace();
            LoggerUtil.info(this.getClass(),e.toString());
        }
        return null;
    }

    /**
     * 获得系统序列号
     *
     * @param fileNumberService2 数据库连接，可以为null
     * @param orgid              组织代码
     * @param bhmc               编号名称
     * @param sfgx               是否更新
     * @return 唯一序列号
     * @author 康庆
     * @version 2009-4-2
     * @since V0.1.0
     */
    public String generate(IFileNumberService fileNumberService2, String orgid, String bhmc, boolean sfgx) {
        synchronized (bhmc) {
            String val = "";
            if (null == fileNumberService2) {
                try {
                    fileNumberService2 = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                    val = generate(fileNumberService2, orgid, bhmc, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            } else {
                // 取出格式定义
                List<Map<String, Object>> seq = getXtcsgs(fileNumberService2, bhmc, orgid);
                if (null == seq || 0 == seq.size()) {
                    throw new BaseException("不能获得名称是【" + bhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                }

                String qz = (String) seq.get(0).get("QZGS"); // 前缀
                if (StringUtils.hasText(qz)) {
                    qz = qz.toUpperCase();
                } else {
                    qz = "";
                }
                String hz = (String) seq.get(0).get("HZGS");// 后缀
                if (StringUtils.hasText(hz)) {
                    hz = hz.toUpperCase();
                } else {
                    hz = "";
                }

                // 流水号格式
                String no = (String) seq.get(0).get("LSHGS");// 后缀
                if (StringUtils.hasText(no)) {
                    no = no.toUpperCase();
                } else {
                    no = "";
                }

                qz = formatPrefix(qz, orgid);
                hz = formatPrefix(hz, orgid);
                DecimalFormat format = new DecimalFormat(no);
                seq.get(0).put("QZ", qz);
                seq.get(0).put("HZ", hz);
                int dqz = this.getValue(seq, fileNumberService2, sfgx);
                String strDqz = format.format(dqz);
                StringBuilder returnValue = new StringBuilder(20);
                val = returnValue.append(qz).append(strDqz).append(hz).toString();
                LOG.info("【" + bhmc + "】取得的编号是【" + val + "】");
            }
            return val;
        }
    }

    /**
     * 获得系统序列号 用于生成编号预览，不实际生成编号
     *
     * @param orgid 组织代码
     * @param xlhmc 序列号名称
     * @param dqz   当前值
     * @return 唯一序列号
     * @author 康庆
     * @version 2018-1-12
     * @since V0.1.0
     */
    public String generate(String orgid, String xlhmc, int dqz) {
        String val = "";
        synchronized (xlhmc) {
            if (null == fileNumberService) {
                try {
                    fileNumberService = (IFileNumberService) Toolkit.getSpringBean(Class
                            .forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }else {
                // 取出格式定义
                List<Map<String, Object>> seq = getXtcsgs(fileNumberService, xlhmc, orgid);
                if (null == seq || 0 == seq.size()) {
                    throw new BaseException("不能获得名称是【" + xlhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                }

                String qz = (String) seq.get(0).get("QZGS"); // 前缀
                if (StringUtils.hasText(qz)) {
                    qz = qz.toUpperCase();
                } else {
                    qz = "";
                }
                String hz = (String) seq.get(0).get("HZGS");// 后缀
                if (StringUtils.hasText(hz)) {
                    hz = hz.toUpperCase();
                } else {
                    hz = "";
                }

                // 流水号格式
                String no = (String) seq.get(0).get("LSHGS");// 后缀
                if (StringUtils.hasText(no)) {
                    no = no.toUpperCase();
                } else {
                    no = "";
                }

                qz = formatPrefix(qz, orgid);
                hz = formatPrefix(hz, orgid);
                DecimalFormat format = new DecimalFormat(no);
                seq.get(0).put("QZ", qz);
                seq.get(0).put("HZ", hz);
                String strDqz = format.format(dqz);
                StringBuilder returnValue = new StringBuilder(20);
                val = returnValue.append(qz).append(strDqz).append(hz).toString();
                LOG.info("【" + xlhmc + "】取得的编号是【" + val + "】");
            }
        }
        return val;
    }

    /**
     * 获得系统序列号，生成规则支持传入参数
     *
     * @param fileNumberService2 数据库连接，可以为null
     * @param orgid              组织代码
     * @param bhmc               编号名称
     * @param replaceMap         使用replaceMap中的值替换规则
     * @param sfgx               是否更新
     * @return 唯一序列号
     * @author 廖声乐
     * @version 2015-8-19
     * @since V0.2.6
     */
    public String generate(IFileNumberService fileNumberService2, String orgid, String bhmc, Map<String, String> replaceMap, boolean sfgx) {
        synchronized (bhmc) {
            String val = "";
            if (null == fileNumberService2) {
                try {
                    if (null == fileNumberService) {
                        fileNumberService2 = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                    }
                    val = generate(fileNumberService2, orgid, bhmc, replaceMap, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            } else {
                // 取出格式定义
                List<Map<String, Object>> seq = getXtcsgs(fileNumberService2, bhmc, orgid);
                if (seq == null) {
                    throw new BaseException("不能获得名称是【" + bhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                }

                String qz = (String) seq.get(0).get("QZGS"); // 前缀
                if (StringUtils.hasText(qz)) {
                    qz = qz.toUpperCase();
                } else {
                    qz = "";
                }
                String hz = (String) seq.get(0).get("HZGS");// 后缀
                if (StringUtils.hasText(hz)) {
                    hz = hz.toUpperCase();
                } else {
                    hz = "";
                }

                String no = (String) seq.get(0).get("LSHGS"); // 流水号格式
                qz = formatPrefix(qz, orgid, replaceMap);
                hz = formatPrefix(hz, orgid, replaceMap);
                DecimalFormat format = new DecimalFormat(no);
                seq.get(0).put("QZ", qz);
                seq.get(0).put("HZ", hz);
                int dqz = this.getValue(seq, fileNumberService2, sfgx);
                String strDqz = format.format(dqz);
                StringBuilder returnValue = new StringBuilder(20);
                val = returnValue.append(qz).append(strDqz).append(hz).toString();
                LOG.info("【" + bhmc + "】取得的编号是【" + val + "】");
            }
            return val;
        }
    }

    /**
     * 获得系统序列号，生成规则支持传入日期，用来替换当前日期
     *
     * @param fileNumberService2 数据库连接，可以为null
     * @param orgid              组织代码
     * @param bhmc               编号名称
     * @param date               使用date替换规则中的日期
     * @param sfgx               是否更新
     * @return 唯一序列号
     * @author 廖声乐
     * @version 2015-8-19
     * @since V0.2.6
     */
    public String generate(IFileNumberService fileNumberService2, String orgid, String bhmc, Date date, boolean sfgx) {
        synchronized (bhmc) {
            String val = "";
            if (null == fileNumberService2) {
                try {
                    fileNumberService2 = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                    val = generate(fileNumberService2, orgid, bhmc, date, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            } else {
                // 取出格式定义
                List<Map<String, Object>> seq = getXtcsgs(fileNumberService2, bhmc, orgid);
                if (seq == null) {
                    throw new BaseException("不能获得名称是【" + bhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                }

                String qz = (String) seq.get(0).get("QZGS"); // 前缀
                if (StringUtils.hasText(qz)) {
                    qz = qz.toUpperCase();
                } else {
                    qz = "";
                }
                String hz = (String) seq.get(0).get("HZGS");// 后缀
                if (StringUtils.hasText(hz)) {
                    hz = hz.toUpperCase();
                } else {
                    hz = "";
                }

                String no = (String) seq.get(0).get("LSHGS"); // 流水号格式
                qz = formatPrefix(qz, orgid, date);
                hz = formatPrefix(hz, orgid, date);
                DecimalFormat format = new DecimalFormat(no);
                seq.get(0).put("QZ", qz);
                seq.get(0).put("HZ", hz);
                int dqz = this.getValue(seq, fileNumberService2, sfgx);
                String strDqz = format.format(dqz);
                StringBuilder returnValue = new StringBuilder(20);
                val = returnValue.append(qz).append(strDqz).append(hz).toString();
                LOG.info("【" + bhmc + "】取得的编号是【" + val + "】");
            }
            return val;
        }
    }

    /**
     * 格式化前缀
     *
     * @param prefix 前缀
     * @param orgId  组织代码
     * @return 唯一序列号
     * @version 2016-9-14
     * @since V0.1.0
     */
    private String formatPrefix(String prefix, String orgId) {
        return this.formatPrefix(prefix, orgId, (Date) null);
    }

    /**
     * 格式化前缀
     *
     * @param prefix 前缀
     * @param orgId  组织代码
     * @param date   指定日期
     * @return 唯一序列号
     * @author 廖声乐
     * @version 2015-8-19
     * @since V0.2.6
     */
    private String formatPrefix(String prefix, String orgId, Date date) {
        Calendar cal = Calendar.getInstance();
        if (date == null) {
            cal.setTime(new Date());
        } else {
            cal.setTime(date);
        }
        String year = cal.get(Calendar.YEAR) + "";
        prefix = prefix.replaceAll("#YEAR#", year);
        prefix = prefix.replaceAll("#MONTH#", String.format("%1$02d", cal.get(Calendar.MONTH) + 1));
        prefix = prefix.replaceAll("#DATE#", String.format("%1$02d", cal.get(Calendar.DATE)));
        prefix = prefix.replaceAll("#HOUR#", String.format("%1$02d", cal.get(Calendar.HOUR_OF_DAY)));
        prefix = prefix.replaceAll("#MINUTE#", String.format("%1$02d", cal.get(Calendar.MINUTE)));
        prefix = prefix.replaceAll("#SECOND#", String.format("%1$02d", cal.get(Calendar.SECOND)));
        prefix = prefix.replaceAll("#MS#", String.format("%1$03d", cal.get(Calendar.MILLISECOND)));
        prefix = prefix.replaceAll("#ORGID#", orgId);
        // 替换用户代号
        // String userId = ActionHelper.getShareId();
        // if(!StringUtils.isEmpty(userId)){
        // IUser user = JDBCUsersCache.getInstance().getUser(userId);
        // if(user != null){
        // prefix = prefix.replaceAll("#USERCODE#",
        // StringUtils.isEmpty(user.getUserCode()) ? "" : user.getUserCode());
        // }
        // }
        // 替换两位的年份
        prefix = prefix.replaceAll("#SHORTYEAR#", year.substring(year.length() - 2));
        return prefix;
    }

    /**
     * 格式化前缀
     *
     * @param prefix     前缀
     * @param orgId      组织代码
     * @param replaceMap 替换值
     * @return 唯一序列号
     * @author 廖声乐
     * @version 2015-8-19
     * @since V0.2.6
     */
    private String formatPrefix(String prefix, String orgId, Map<String, String> replaceMap) {
        prefix = formatPrefix(prefix, orgId);
        if (replaceMap != null && replaceMap.size() > 0) {
            for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
                prefix = prefix.replaceAll("#" + entry.getKey() + "#", entry.getValue());
            }
        }
        return prefix;
    }

    /**
     * 根据序列号名称与ORGID查询出序列号信息
     *
     * @param fileNumberService2 数据库连接
     * @param xlhmc              序列号名称
     * @param orgid              组织代码
     * @return 序列号信息
     * @since V0.1.0
     */
    private List<Map<String, Object>> getXtcsgs(IFileNumberService fileNumberService2, String xlhmc, String orgid) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("BHMC", xlhmc);
        param.put("ORGID", orgid);
        return fileNumberService2.findFileNumberRule4ID(param);
    }

    private int getValue(List<Map<String, Object>> seq, IFileNumberService fileNumberService2, boolean sfgx) {
        int minVal = getMinValue(seq, fileNumberService2);
        int currVal = getCurrValue(seq, fileNumberService2);

        // add by 廖声乐 2015-01-22 解决因为定义编号规则修改，导致的生成的编号小于定义的最小编号的问题
        Integer defMin = Integer.parseInt(seq.get(0).get("ZXZ") + "");
        // if(null == defMin){
        // defMin = 0;
        // }
        if (minVal > 0 && minVal <= currVal && minVal >= defMin) {
            // 如果要求更新数据库 只需要删除需要使用的号码 因为可能已经释放了多个
            if (sfgx) {
                try {
                    seq.get(0).put("MINVAL", minVal);
                    fileNumberService2.deleteXH4ID(seq.get(0));
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            return minVal;
        }
        currVal++;

        // add by 廖声乐 2015-01-22 解决因为定义编号规则修改，导致的生成的编号小于定义的最小编号的问题
        if (currVal < defMin) {
            currVal = defMin;
        }

        return updateCurrValue(seq, fileNumberService2, sfgx, currVal);
    }

    /**
     * 获取最小值
     *
     * @param seq                序列号信息
     * @param fileNumberService2 数据库连接
     * @return 最小值
     * @version 2016-9-14
     * @since V0.1.0
     */
    private int getMinValue(List<Map<String, Object>> seq, IFileNumberService fileNumberService2) {
        try {
            // 取已经释放的最小号码
            List<Map<String, Object>> result = fileNumberService2.getMinDqz4ID(seq.get(0));
            int minVal = 0;
            if (null != result && 0 < result.size() && null != result.get(0)) {
                minVal = Integer.parseInt(result.get(0).get("MINVAL") + "");

            }
            return minVal;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return 0;
    }

    /**
     * 获取当前值
     *
     * @param seq                序列号信息
     * @param fileNumberService2 数据库连接
     * @return 当前值
     * @version 2016-9-14
     * @since V0.1.0
     */
    private int getCurrValue(List<Map<String, Object>> seq, IFileNumberService fileNumberService2) {
        int currVal = 0;
        try {
            List<Map<String, Object>> result = fileNumberService2.getCurrVal4ID(seq.get(0));
            if (null != result && 0 < result.size() && null != result.get(0)) {
                currVal = Integer.parseInt(result.get(0).get("DQZ") + "");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return currVal;
    }

    /**
     * 更新当前值
     *
     * @param seq                序列号信息
     * @param fileNumberService2 数据库连接
     * @param sfgx
     * @return 当前值
     * @version 2016-9-14
     * @since V0.1.0
     */
    private int updateCurrValue(List<Map<String, Object>> seq, IFileNumberService fileNumberService2, boolean sfgx, int dqz) {
        // 如果不只要求查看
        if (sfgx) {
            try {
                // 如果没有记录则添加一个
                if (dqz == Integer.parseInt(seq.get(0).get("ZXZ") + "")) {
                    Map<String, Object> param = new HashMap<String, Object>();
                    param.put("XH", Toolkit.getID());
                    param.put("SXBH", seq.get(0).get("SXBH"));
                    param.put("BHLX", "0");
                    Integer zxz = Integer.parseInt(seq.get(0).get("ZXZ") + "");
                    Integer zdz = Integer.parseInt(seq.get(0).get("ZDZ") + "");
                    param.put("ZXZ", null == zxz ? (Integer)0 : zxz);
                    param.put("ZDZ", null == zdz ? (Integer)0 : zdz);
                    if (zxz != null && zxz > 1) {
                        dqz = zxz;
                    }
                    param.put("DQZ", dqz);
                    param.put("QZ", seq.get(0).get("QZ"));
                    param.put("HZ", seq.get(0).get("HZ"));
                    param.put("BZ", null == seq.get(0).get("BZ") ? "" : seq.get(0).get("BZ"));
                    param.put("ORGID", seq.get(0).get("ORGID"));
                    Date now = new Date(System.currentTimeMillis());
                    param.put("CJSJ", now);
                    param.put("XGSJ", now);
                    fileNumberService2.addfileNumber4ID(param);
                }
                // 更新记录表
                Map<String, Object> param = new HashMap<String, Object>();
                param.put("DQZ", dqz);
                param.put("SXBH", seq.get(0).get("SXBH"));
                param.put("QZ", seq.get(0).get("QZ"));
                param.put("ORGID", seq.get(0).get("ORGID"));
                fileNumberService2.updateFileNumber4ID(param);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 增加返回值解决获取最小编号的问题
        // modify by 廖声乐 2012-04-28
        return dqz;
    }

    /**
     * 释放编号,不需要传链接。从本地线程中获取链接。
     *
     * @param orgid
     * @param bhmc  编号名称
     * @param bh    编号
     * @param user  用户
     * @param sfgx  是否更新
     * @throws SQLException
     */
    public void free(String orgid, String bhmc, String bh, String user, boolean sfgx) {
        if (null == fileNumberService) {
            try {
                fileNumberService = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        this.free(fileNumberService, orgid, bhmc, bh, user, sfgx);
    }

    /**
     * 释放编号
     *
     * @param fileNumberService2 数据库连接
     * @param orgId
     * @param bhmc               编号名称
     * @param bh                 编号
     * @param user               用户
     * @param sfgx               是否更新
     * @throws SQLException
     */
    public void free(IFileNumberService fileNumberService2, String orgId, String bhmc, String bh, String user, boolean sfgx) {
        Map<String, String> map = new HashMap<String, String>();
        this.free(fileNumberService2, orgId, bhmc, bh, user, map, sfgx);
    }

    /**
     * 回收编号，支持跨年月回收
     *
     * @param fileNumberService2 数据库连接
     * @param orgid              ORGID
     * @param bhmc               编号名称
     * @param bh                 编号
     * @param user               用户ID
     * @param date               日期
     * @param sfgx               是否更新
     * @author 廖声乐
     * @version 2016年1月22日
     * @since V0.2.0
     */
    public void free(IFileNumberService fileNumberService2, String orgid, String bhmc, String bh, String user, Date date, boolean sfgx) {
        synchronized (bhmc) {
            if (fileNumberService2 == null) {
                try {
                    fileNumberService2 = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                    free(fileNumberService2, orgid, bhmc, bh, user, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            } else {
                try {
                    // 取出格式定义
                    List<Map<String, Object>> seq = getXtcsgs(fileNumberService2, bhmc, orgid);
                    if (seq == null) {
                        throw new BaseException("不能获得名称是【" + bhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                    }
                    String qz = (String) seq.get(0).get("QZGS"); // 前缀
                    if (StringUtils.hasText(qz)) {
                        qz = qz.toUpperCase();
                    } else {
                        qz = "";
                    }
                    String hz = (String) seq.get(0).get("HZGS");// 后缀
                    if (StringUtils.hasText(hz)) {
                        hz = hz.toUpperCase();
                    } else {
                        hz = "";
                    }
                    // String no = BeanUtils.getString(seq,"LSHGS"); //流水号格式
                    if (date != null) {
                        qz = formatPrefix(qz, orgid, date);
                        hz = formatPrefix(hz, orgid, date);
                    } else {
                        qz = formatPrefix(qz, orgid);
                        hz = formatPrefix(hz, orgid);
                    }
                    // 如果作替换,释放编号后再获得编号会有问题
                    // modify by 廖声乐 2012-04-23
                    // bh = bh.replaceAll("\\[", "").replaceAll("\\]", "");
                    // qz = qz.replaceAll("\\[", "").replaceAll("\\]", "");
                    // hz = hz.replaceAll("\\[", "").replaceAll("\\]", "");
                    seq.get(0).put("QZ", qz);
                    seq.get(0).put("HZ", hz);
                    String strDqz = bh.replace(qz, "").replace(hz, "");
                    this.delete(fileNumberService2, seq, strDqz, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 回收编号，支持生成规则回收
     *
     * @param fileNumberService2 数据库连接
     * @param orgid              ORGID
     * @param bhmc               编号名称
     * @param bh                 编号
     * @param user               用户ID
     * @param replaceMap         使用replaceMap中的值替换规则
     * @param sfgx               是否更新
     * @author 廖声乐
     * @version 2016年1月22日
     * @since V0.2.0
     */
    public void free(IFileNumberService fileNumberService2, String orgid, String bhmc, String bh, String user, Map<String, String> replaceMap, boolean sfgx) {
        synchronized (bhmc) {
            if (fileNumberService2 == null) {
                try {
                    fileNumberService2 = (IFileNumberService) Toolkit.getSpringBean(Class.forName("com.szboanda.platform.system.filenumber.service.impl.FileNumberServiceImpl"));
                    free(fileNumberService2, orgid, bhmc, bh, user, replaceMap, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            } else {
                try {
                    // 取出格式定义
                    List<Map<String, Object>> seq = getXtcsgs(fileNumberService2, bhmc, orgid);
                    if (seq == null) {
                        throw new BaseException("不能获得名称是【" + bhmc + "】的序列号定义,请确认已经完成了正确的配置!");
                    }
                    String qz = (String) seq.get(0).get("QZGS"); // 前缀
                    if (StringUtils.hasText(qz)) {
                        qz = qz.toUpperCase();
                    } else {
                        qz = "";
                    }
                    String hz = (String) seq.get(0).get("HZGS");// 后缀
                    if (StringUtils.hasText(hz)) {
                        hz = hz.toUpperCase();
                    } else {
                        hz = "";
                    }

                    qz = formatPrefix(qz, orgid, replaceMap);
                    hz = formatPrefix(hz, orgid, replaceMap);
                    // 如果作替换,释放编号后再获得编号会有问题
                    seq.get(0).put("QZ", qz);
                    seq.get(0).put("HZ", hz);
                    String strDqz = bh.replace(qz, "").replace(hz, "");
                    this.delete(fileNumberService2, seq, strDqz, sfgx);
                } catch (Exception e) {
                    throw new BaseException(e.getMessage(), e);
                }
            }
        }
    }

    private void delete(IFileNumberService fileNumberService2, List<Map<String, Object>> seq, String strDqz, boolean sfgx) throws Exception {
        try {
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("SXBH", seq.get(0).get("SXBH"));
            Integer dqz = Integer.parseInt(strDqz);
            param.put("DQZ", dqz == null ? (Integer)0 : dqz);
            param.put("QZ", seq.get(0).get("QZ"));
            param.put("ORGID", seq.get(0).get("ORGID"));
            int total = fileNumberService2.getTotalXH4ID(param);
            if (total == 0) {
                Map<String, Object> param2 = new HashMap<String, Object>();
                param2.put("XH", Toolkit.getID());
                param2.put("SXBH", seq.get(0).get("SXBH"));
                param2.put("BHLX", "1");
                Integer zdz = Integer.parseInt(seq.get(0).get("ZDZ") + "");
                Integer zxz = Integer.parseInt(seq.get(0).get("ZXZ") + "");
                param2.put("ZDZ", zdz == null ? (Integer)0 : zdz);
                param2.put("ZXZ", zxz == null ? (Integer)0 : zxz);
                Long dqzLong = Long.parseLong(strDqz);
                param2.put("DQZ", dqzLong);
                param2.put("QZ", seq.get(0).get("QZ"));
                param2.put("HZ", seq.get(0).get("HZ"));
                param2.put("BZ", null == seq.get(0).get("BZ") ? "" : seq.get(0).get("BZ"));
                param2.put("ORGID", seq.get(0).get("ORGID"));
                Date now = new Date(System.currentTimeMillis());
                param2.put("CJSJ", now);
                param2.put("XGSJ", now);
                fileNumberService2.addfileNumber4ID(param2);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    public static void main(String[] args) {
        // System.out.println(String.format("%1$04d", Calendar.getInstance().get(Calendar.YEAR)));
        // System.out.println(String.format("%1$02d", Calendar.getInstance().get(Calendar.MONTH) + 1));
        // System.out.println(String.format("%1$02d", Calendar.getInstance().get(Calendar.DAY_OF_MONTH)));
        // System.out.println(String.format("%1$02d", Calendar.getInstance().get(Calendar.DATE)));
        // System.out.println(String.format("%1$02d", Calendar.getInstance().get(Calendar.HOUR_OF_DAY)));
        // System.out.println(String.format("%1$02d", Calendar.getInstance().get(Calendar.MINUTE)));
        // System.out.println(String.format("%1$02d", Calendar.getInstance().get(Calendar.SECOND)));
        // System.out.println(String.format("%1$03d", Calendar.getInstance().get(Calendar.MILLISECOND)));
        // System.out.printf("%1$02d", 2);
        // String xmbh = IDGenerator.getInstance().generate(null, "320281",
        // "办文编号", true);
        DecimalFormat format = new DecimalFormat("300240");
        String xmbh = format.format(1);
        System.out.println(xmbh);
    }

}
